/**
 * 文件工具函数
 */

/**
 * 下载文件
 * @param {string|Blob} data - 文件数据（URL字符串或Blob对象）
 * @param {string} filename - 文件名
 * @param {string} mimeType - MIME类型
 */
export function downloadFile(
  data,
  filename,
  mimeType = 'application/octet-stream'
) {
  let blob;

  if (typeof data === 'string') {
    // 如果是URL字符串，创建一个包含URL的Blob
    blob = new Blob([data], { type: mimeType });
  } else if (data instanceof Blob) {
    blob = data;
  } else {
    throw new Error('数据必须是字符串或Blob对象');
  }

  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  link.style.display = 'none';

  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);

  // 清理URL对象
  setTimeout(() => URL.revokeObjectURL(url), 100);
}

/**
 * 从URL下载文件
 * @param {string} url - 文件URL
 * @param {string} filename - 文件名
 */
export function downloadFileFromUrl(url, filename) {
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  link.target = '_blank';
  link.style.display = 'none';

  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

/**
 * 将文本内容下载为文件
 * @param {string} content - 文本内容
 * @param {string} filename - 文件名
 * @param {string} mimeType - MIME类型
 */
export function downloadTextFile(content, filename, mimeType = 'text/plain') {
  const blob = new Blob([content], { type: mimeType });
  downloadFile(blob, filename, mimeType);
}

/**
 * 将JSON数据下载为文件
 * @param {any} data - JSON数据
 * @param {string} filename - 文件名
 * @param {number} space - JSON格式化空格数
 */
export function downloadJSONFile(data, filename, space = 2) {
  const content = JSON.stringify(data, null, space);
  downloadTextFile(content, filename, 'application/json');
}

/**
 * 将Canvas内容下载为图片
 * @param {HTMLCanvasElement} canvas - Canvas元素
 * @param {string} filename - 文件名
 * @param {string} format - 图片格式 ('png' | 'jpeg' | 'webp')
 * @param {number} quality - 图片质量 (0-1)
 */
export function downloadCanvasAsImage(
  canvas,
  filename,
  format = 'png',
  quality = 1
) {
  const mimeType = `image/${format}`;
  canvas.toBlob(
    blob => {
      if (blob) {
        downloadFile(blob, filename, mimeType);
      }
    },
    mimeType,
    quality
  );
}

/**
 * 文件上传
 * @param {File} file - 文件对象
 * @param {string} url - 上传URL
 * @param {Object} options - 选项
 * @returns {Promise} 上传结果
 */
export function uploadFile(file, url, options = {}) {
  const { onProgress, onSuccess, onError, headers = {}, data = {} } = options;

  return new Promise((resolve, reject) => {
    const formData = new FormData();
    formData.append('file', file);

    // 添加额外数据
    Object.keys(data).forEach(key => {
      formData.append(key, data[key]);
    });

    const xhr = new XMLHttpRequest();

    // 上传进度
    if (onProgress) {
      xhr.upload.addEventListener('progress', event => {
        if (event.lengthComputable) {
          const percentComplete = (event.loaded / event.total) * 100;
          onProgress(percentComplete);
        }
      });
    }

    // 请求完成
    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        const response = xhr.responseText;
        try {
          const jsonResponse = JSON.parse(response);
          onSuccess && onSuccess(jsonResponse);
          resolve(jsonResponse);
        } catch (e) {
          onSuccess && onSuccess(response);
          resolve(response);
        }
      } else {
        const error = new Error(`上传失败: ${xhr.status} ${xhr.statusText}`);
        onError && onError(error);
        reject(error);
      }
    });

    // 请求错误
    xhr.addEventListener('error', () => {
      const error = new Error('网络错误');
      onError && onError(error);
      reject(error);
    });

    xhr.open('POST', url);

    // 设置请求头
    Object.keys(headers).forEach(key => {
      xhr.setRequestHeader(key, headers[key]);
    });

    xhr.send(formData);
  });
}

/**
 * 多文件上传
 * @param {FileList|File[]} files - 文件列表
 * @param {string} url - 上传URL
 * @param {Object} options - 选项
 * @returns {Promise} 上传结果
 */
export function uploadFiles(files, url, options = {}) {
  const {
    onProgress,
    onSuccess,
    onError,
    concurrent = 3, // 并发上传数量
  } = options;

  const fileArray = Array.from(files);
  const results = [];
  let completed = 0;

  return new Promise((resolve, reject) => {
    const uploadNext = index => {
      if (index >= fileArray.length) {
        resolve(results);
        return;
      }

      const file = fileArray[index];
      const fileOptions = {
        ...options,
        onProgress: progress => {
          onProgress &&
            onProgress({
              fileIndex: index,
              fileName: file.name,
              progress,
              totalFiles: fileArray.length,
              completedFiles: completed,
            });
        },
        onSuccess: response => {
          results[index] = { success: true, file, response };
          completed++;
          onSuccess && onSuccess({ file, response, index });
          uploadNext(index + concurrent);
        },
        onError: error => {
          results[index] = { success: false, file, error };
          completed++;
          onError && onError({ file, error, index });
          uploadNext(index + concurrent);
        },
      };

      uploadFile(file, url, fileOptions).catch(() => {
        uploadNext(index + concurrent);
      });
    };

    // 启动并发上传
    for (let i = 0; i < Math.min(concurrent, fileArray.length); i++) {
      uploadNext(i);
    }
  });
}

/**
 * 文件预览
 * @param {File} file - 文件对象
 * @param {string} type - 预览类型 ('image' | 'text' | 'json')
 * @returns {Promise} 预览结果
 */
export function previewFile(file, type = 'image') {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = event => {
      resolve({
        file,
        data: event.target.result,
        type: file.type,
        size: file.size,
        name: file.name,
      });
    };

    reader.onerror = () => {
      reject(new Error('文件读取失败'));
    };

    switch (type) {
      case 'image':
        reader.readAsDataURL(file);
        break;
      case 'text':
        reader.readAsText(file);
        break;
      case 'json':
        reader.readAsText(file);
        break;
      default:
        reader.readAsDataURL(file);
    }
  });
}

/**
 * 图片预览
 * @param {File} file - 图片文件
 * @param {Object} options - 选项
 * @returns {Promise} 预览结果
 */
export function previewImage(file, options = {}) {
  const { maxWidth = 800, maxHeight = 600, quality = 0.8 } = options;

  return new Promise((resolve, reject) => {
    if (!file.type.startsWith('image/')) {
      reject(new Error('文件不是图片类型'));
      return;
    }

    const reader = new FileReader();
    reader.onload = event => {
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');

        // 计算缩放比例
        let { width, height } = img;
        if (width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height);
          width *= ratio;
          height *= ratio;
        }

        canvas.width = width;
        canvas.height = height;

        // 绘制图片
        ctx.drawImage(img, 0, 0, width, height);

        // 转换为Blob
        canvas.toBlob(
          blob => {
            resolve({
              file,
              originalSize: { width: img.width, height: img.height },
              previewSize: { width, height },
              dataUrl: event.target.result,
              blob,
              canvas,
            });
          },
          file.type,
          quality
        );
      };

      img.onerror = () => {
        reject(new Error('图片加载失败'));
      };

      img.src = event.target.result;
    };

    reader.onerror = () => {
      reject(new Error('文件读取失败'));
    };

    reader.readAsDataURL(file);
  });
}

/**
 * 文件格式验证
 * @param {File} file - 文件对象
 * @param {Object} options - 验证选项
 * @returns {Object} 验证结果
 */
export function validateFile(file, options = {}) {
  const {
    allowedTypes = [],
    maxSize = 10 * 1024 * 1024, // 10MB
    allowedExtensions = [],
  } = options;

  const result = {
    isValid: true,
    errors: [],
  };

  // 检查文件大小
  if (file.size > maxSize) {
    result.isValid = false;
    result.errors.push(`文件大小超过限制 (${formatFileSize(maxSize)})`);
  }

  // 检查文件类型
  if (allowedTypes.length > 0 && !allowedTypes.includes(file.type)) {
    result.isValid = false;
    result.errors.push(`不支持的文件类型: ${file.type}`);
  }

  // 检查文件扩展名
  if (allowedExtensions.length > 0) {
    const extension = getFileExtension(file.name);
    if (!allowedExtensions.includes(extension)) {
      result.isValid = false;
      result.errors.push(`不支持的文件扩展名: ${extension}`);
    }
  }

  return result;
}

/**
 * 获取文件扩展名
 * @param {string} filename - 文件名
 * @returns {string} 扩展名
 */
export function getFileExtension(filename) {
  if (!filename || typeof filename !== 'string') {
    return '';
  }
  const lastDot = filename.lastIndexOf('.');
  return lastDot > 0 ? filename.substring(lastDot + 1).toLowerCase() : '';
}

/**
 * 获取文件MIME类型
 * @param {string} extension - 文件扩展名
 * @returns {string} MIME类型
 */
export function getMimeType(extension) {
  const mimeTypes = {
    // 图片
    jpg: 'image/jpeg',
    jpeg: 'image/jpeg',
    png: 'image/png',
    gif: 'image/gif',
    webp: 'image/webp',
    svg: 'image/svg+xml',
    bmp: 'image/bmp',
    ico: 'image/x-icon',

    // 文档
    pdf: 'application/pdf',
    doc: 'application/msword',
    docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    xls: 'application/vnd.ms-excel',
    xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    ppt: 'application/vnd.ms-powerpoint',
    pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    txt: 'text/plain',
    rtf: 'application/rtf',

    // 压缩文件
    zip: 'application/zip',
    rar: 'application/x-rar-compressed',
    '7z': 'application/x-7z-compressed',
    tar: 'application/x-tar',
    gz: 'application/gzip',

    // 音频
    mp3: 'audio/mpeg',
    wav: 'audio/wav',
    ogg: 'audio/ogg',
    aac: 'audio/aac',
    flac: 'audio/flac',

    // 视频
    mp4: 'video/mp4',
    avi: 'video/x-msvideo',
    mov: 'video/quicktime',
    wmv: 'video/x-ms-wmv',
    flv: 'video/x-flv',
    webm: 'video/webm',

    // 代码文件
    js: 'application/javascript',
    css: 'text/css',
    html: 'text/html',
    htm: 'text/html',
    xml: 'application/xml',
    json: 'application/json',
    csv: 'text/csv',
  };

  return mimeTypes[extension.toLowerCase()] || 'application/octet-stream';
}

/**
 * 文件拖拽处理
 * @param {HTMLElement} element - 拖拽目标元素
 * @param {Object} options - 选项
 * @returns {Object} 控制对象
 */
export function createFileDropZone(element, options = {}) {
  const {
    onDrop,
    onDragOver,
    onDragLeave,
    onDragEnter,
    multiple = true,
    accept = [],
  } = options;

  let isDragOver = false;

  const handleDragOver = event => {
    event.preventDefault();
    event.stopPropagation();

    if (!isDragOver) {
      isDragOver = true;
      element.classList.add('drag-over');
      onDragOver && onDragOver(event);
    }
  };

  const handleDragLeave = event => {
    event.preventDefault();
    event.stopPropagation();

    if (isDragOver) {
      isDragOver = false;
      element.classList.remove('drag-over');
      onDragLeave && onDragLeave(event);
    }
  };

  const handleDragEnter = event => {
    event.preventDefault();
    event.stopPropagation();
    onDragEnter && onDragEnter(event);
  };

  const handleDrop = event => {
    event.preventDefault();
    event.stopPropagation();

    isDragOver = false;
    element.classList.remove('drag-over');

    const files = Array.from(event.dataTransfer.files);

    if (!multiple && files.length > 1) {
      console.warn('只允许单个文件');
      return;
    }

    // 过滤文件类型
    let filteredFiles = files;
    if (accept.length > 0) {
      filteredFiles = files.filter(file => {
        const extension = getFileExtension(file.name);
        return accept.includes(extension) || accept.includes(file.type);
      });
    }

    onDrop && onDrop(filteredFiles, event);
  };

  // 绑定事件
  element.addEventListener('dragover', handleDragOver);
  element.addEventListener('dragleave', handleDragLeave);
  element.addEventListener('dragenter', handleDragEnter);
  element.addEventListener('drop', handleDrop);

  // 返回控制对象
  return {
    destroy() {
      element.removeEventListener('dragover', handleDragOver);
      element.removeEventListener('dragleave', handleDragLeave);
      element.removeEventListener('dragenter', handleDragEnter);
      element.removeEventListener('drop', handleDrop);
      element.classList.remove('drag-over');
    },

    updateOptions(newOptions) {
      Object.assign(options, newOptions);
    },
  };
}

/**
 * 文件选择器
 * @param {Object} options - 选项
 * @returns {Promise} 选择的文件
 */
export function selectFiles(options = {}) {
  const { multiple = false, accept = [], capture = false } = options;

  return new Promise((resolve, reject) => {
    const input = document.createElement('input');
    input.type = 'file';
    input.multiple = multiple;
    input.capture = capture;

    if (accept.length > 0) {
      input.accept = accept
        .map(type => {
          if (type.startsWith('.')) {
            return type;
          }
          return `.${type}`;
        })
        .join(',');
    }

    input.onchange = event => {
      const files = Array.from(event.target.files);
      resolve(multiple ? files : files[0] || null);
    };

    input.oncancel = () => {
      resolve(multiple ? [] : null);
    };

    input.click();
  });
}

/**
 * 文件大小格式化（从format.js导入，避免重复）
 * @param {number} bytes - 字节数
 * @param {number} decimals - 小数位数
 * @returns {string} 格式化后的文件大小
 */
function formatFileSize(bytes, decimals = 2) {
  if (bytes === 0) {
    return '0 Bytes';
  }

  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
